package com.azzcs.session;

import com.azzcs.executor.Executor;
import com.azzcs.executor.SimpleExecutor;
import com.azzcs.parse.Configuration;
import com.azzcs.parse.MappedStatement;

import java.lang.reflect.*;
import java.util.List;

/**
 * @Author: wzg
 * @Date: 2020/12/6 上午10:51
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;

    public DefaultSqlSession(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public <T> T selectOne(String statementId, Object... param) throws Exception {
        List<T> list = selectList(statementId, param);
        if(list == null || list.size() == 0){
            return null;
        }
        if (list.size() == 1) {
            return list.get(0);
        } else {
            throw new RuntimeException("查询的数据不止一条");
        }
    }

    @Override
    public <T> List<T> selectList(String statementId, Object... param) throws Exception {
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        Executor executor = new SimpleExecutor();
        List<T> query = executor.query(configuration, mappedStatement, param);
        return query;
    }

    @Override
    public <T> T getMapper(Class clazz) {
        Object proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Exception {

                String statementId = getStatementId(method);

                MappedStatement mappedStatement = configuration
                        .getMappedStatementMap()
                        .get(statementId);

                Object result = null;
                switch (mappedStatement.getCommandType()){
                    case INSERT:
                        result = insert(statementId,args);
                        break;
                    case DELETE:
                        result = delete(statementId,args);
                        break;
                    case UPDATE:
                        result = update(statementId,args);
                        break;
                    case SELECT:
                        result = select(method,statementId,args);
                        break;
                }
                return result;
            }


        });
        return (T)proxyObj;
    }

    private String getStatementId(Method method) {
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        return className+"."+methodName;
    }

    private Object select(Method method, String statementId, Object[] args) throws Exception {
        Type genericReturnType = method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType){
            List<Object> objects = selectList(statementId, args);
            return objects;
        }
        return selectOne(statementId,args);
    }

    @Override
    public int update(String statementId, Object... parameter) throws Exception {
        MappedStatement mappedStatement = configuration.getMappedStatementMap().get(statementId);
        Executor executor = new SimpleExecutor();
        return executor.update(configuration, mappedStatement, parameter);
    }

    @Override
    public int insert(String statement, Object... parameter) throws Exception {
        return update(statement,parameter);
    }

    @Override
    public int delete(String statement, Object... parameter) throws Exception {
        return update(statement,parameter);
    }
}
